
package privatemessanger;
import java.net.Socket;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This class contains the socket of a real server.
 * @author  Erez Fatal, Oren Slor, Elad Yanai, Sigal Agami, Chen Ben Shabat,
 *          Inbar Pardo, Islamm Heralla, Ziv Hadary, Oren Shalev, Ortal David.
 */
public class ConnectToServer extends Thread
{
    private Socket _socket;
    private PrintWriter _sendInfo;
    private BufferedReader _getInfo;
    private String _string,_header;
    private Client _client;

    /**
     * This is the ConnectToServer constructor.
     * @param socket A connection with a new client.
     * @throws IOException
     */
    ConnectToServer(Socket socket) throws IOException
    {
        super();
        _socket= socket;
        System.out.println("we have a new client!");
        System.out.println("socket was created with ** client **="+_socket.getInetAddress() );
    }

    @Override
    /**
     * This method reads from the socket.
     */
    public void run()
    {
        try {
            _getInfo = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
            _sendInfo = new PrintWriter(_socket.getOutputStream(), true);
            while(true)
            {
                _string= _getInfo.readLine();
                parser(_string);
                if (_string==null || _string.equals("BYE") || _string.equals("OK_DELETE"))
                    break;
            }
        } catch (IOException ex) { Logger.getLogger(ConnectToServer.class.getName()).log(Level.SEVERE, null, ex); }
    }

    /**
     * Get The client of this connection.
     * @return The client.
     */
    public Client getClient() { return _client; }

    /**
     * This methood has to handle incoming messages.
     * @param str String from the socket.
     */
    void parser(String str)
    {
        if (str==null)
            return;
        String[] words=str.split(" ");

        if (words[0].equals("HELLO"))
        {
            int ID=Integer.decode(words[3]);
            _client=new Client(words[1], words[2], ID, words[4]);
            MainFrame._statisticsInfo.setCurrentUsers(true);
            MainFrame._user.getServerArray().get(0).addClient(_client);
            MainFrame._serverName.updateList();
            writeSocket("WELCOME "+MainFrame._user.getIP()+" "+MainFrame._user.getServerArray().get(0).getServerName());
            writeSocket("NEW_CONTACT "+MainFrame._user.getServerArray().get(0).getClientArray().get(0).getUserName()+" "+MainFrame._user.getServerArray().get(0).getClientArray().get(0).getType()+" "+MainFrame._user.getServerArray().get(0).getClientArray().get(0).getID()+" "+MainFrame._user.getServerArray().get(0).getClientArray().get(0).getIP());
            for (int i=1; i<MainFrame._user.getServerArray().get(0).getConnectionArray().size(); i++)
            {
                if (MainFrame._user.getServerArray().get(0).isOpen())
                    writeSocket("NEW_CONTACT "+MainFrame._user.getServerArray().get(0).getClientArray().get(i).getUserName()+" "+MainFrame._user.getServerArray().get(0).getClientArray().get(i).getType()+" "+MainFrame._user.getServerArray().get(0).getClientArray().get(i).getID()+" "+MainFrame._user.getServerArray().get(0).getClientArray().get(i).getIP());
                else if (MainFrame._user.getServerArray().get(0).getClientArray().get(i).getType().equalsIgnoreCase(_client.getType()))
                    writeSocket("NEW_CONTACT "+MainFrame._user.getServerArray().get(0).getClientArray().get(i).getUserName()+" "+MainFrame._user.getServerArray().get(0).getClientArray().get(i).getType()+" "+MainFrame._user.getServerArray().get(0).getClientArray().get(i).getID()+" "+MainFrame._user.getServerArray().get(0).getClientArray().get(i).getIP());
            }
            for (int i=0; i<MainFrame._user.getServerArray().get(0).getConnectionArray().size(); i++)
            {
                if (MainFrame._user.getServerArray().get(0).isOpen())
                {
                    if (MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getID()!=ID)
                        MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).writeSocket("NEW_CONTACT "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(MainFrame._user.getServerArray().get(0).getConnectionArray().size()-1).getClient().getUserName()+" "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(MainFrame._user.getServerArray().get(0).getConnectionArray().size()-1).getClient().getType()+" "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(MainFrame._user.getServerArray().get(0).getConnectionArray().size()-1).getClient().getID()+" "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(MainFrame._user.getServerArray().get(0).getConnectionArray().size()-1).getClient().getIP());
                }
                else if (MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getType().equalsIgnoreCase(_client.getType()))
                {
                    if (MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getID()!=ID)
                        MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).writeSocket("NEW_CONTACT "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(MainFrame._user.getServerArray().get(0).getConnectionArray().size()-1).getClient().getUserName()+" "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(MainFrame._user.getServerArray().get(0).getConnectionArray().size()-1).getClient().getType()+" "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(MainFrame._user.getServerArray().get(0).getConnectionArray().size()-1).getClient().getID()+" "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(MainFrame._user.getServerArray().get(0).getConnectionArray().size()-1).getClient().getIP());
                }
            }
        }

        if (words[0].equals("MESSAGE"))
        {
            MainFrame._statisticsInfo.setMessageCounter();
            _header=words[1]+" "+words[2]+" "+words[3]+" "+words[4]+" "+words[5];
            String message="";
            for (int i=6; i<words.length; i++)
            {
                if (message.equals(""))
                    message=words[6];
                else
                    message+=" "+words[i];
            }
            int receiverID=Integer.decode(words[3]);
            if (receiverID==MainFrame._user.getID())
            {
                MainFrame._user.getMessageArray().add(Message.Create(_header,message));
                MainFrame._popUp.setText("You received a new message from "+MainFrame._user.getMessageArray().get(MainFrame._user.getMessageArray().size()-1).getSenderName());
                MainFrame._popUp.setVisible(true);
                MainFrame._message.cleanText();
                MainFrame._contactName.cleanSelectedClient();
                MainFrame._text.getSendButton().setEnabled(false);
                int contactIndex=MainFrame._contactName.getList().getSelectedIndex();
                int serverIndex=MainFrame._serverName.getList().getSelectedIndex();
                if (contactIndex!=-1 && serverIndex!=-1)
                {
                    if (MainFrame._user.getServerArray().get(serverIndex).getClientArray().get(contactIndex).getID()!=MainFrame._user.getID())
                    {
                        MainFrame._contactName.setSelectedClient(MainFrame._user.getServerArray().get(serverIndex).getClientArray().get(contactIndex));
                        MainFrame._text.getSendButton().setEnabled(true);
                        for (int i=0; i<MainFrame._user.getMessageArray().size(); i++)
                        {
                            if (MainFrame._user.getMessageArray().get(i).getSenderID()==MainFrame._user.getServerArray().get(serverIndex).getClientArray().get(contactIndex).getID() || MainFrame._user.getMessageArray().get(i).getReceiverID()==MainFrame._user.getServerArray().get(serverIndex).getClientArray().get(contactIndex).getID())
                                MainFrame._message.addText(MainFrame._user.getMessageArray().get(i));
                        }
                    }
                }
            }
            else
            {
                for (int i=0; i<MainFrame._user.getServerArray().get(0).getConnectionArray().size(); i++)
                {
                    if (MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getID()==receiverID && MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getUserName().equals(words[4]))
                        MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).writeSocket(str);
                }
            }
            _header="";
        }

        if (words[0].equals("NEW_TYPE"))
        {
            _client.setType(words[1]);
            MainFrame._serverName.updateList();
            if (MainFrame._user.getServerArray().get(0).isOpen())
            {
                for (int i=0; i<MainFrame._user.getServerArray().get(0).getConnectionArray().size(); i++)
                {
                    if (MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getID()!=_client.getID())
                        MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).writeSocket("NEW_TYPE "+_client.getID()+" "+_client.getUserName()+" "+_client.getType());
                }
                return;
            }
            for (int i=0; i<MainFrame._user.getServerArray().get(0).getConnectionArray().size(); i++)
            {
                if (MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getID()!=_client.getID())
                    MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).writeSocket("REMOVE_CONTACT "+_client.getID()+" "+_client.getUserName());
            }
            writeSocket("REMOVE_ALL");
            for (int i=0; i<MainFrame._user.getServerArray().get(0).getConnectionArray().size(); i++)
            {
                if (MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getID()!=_client.getID() && MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getType().equalsIgnoreCase(words[1]))
                {
                    writeSocket("NEW_CONTACT "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getUserName()+" "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getType()+" "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getID()+" "+MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getIP());
                    MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).writeSocket("NEW_CONTACT "+_client.getUserName()+" "+ _client.getType()+" "+ _client.getID()+" "+ _client.getIP());
                }
            }
            MainFrame._serverName.updateList();
        }

        if (words[0].equals("BYE"))
        {
            MainFrame._statisticsInfo.setCurrentUsers(false);
            MainFrame._user.getServerArray().get(0).removeClient(_client);
            for (int i=0; i<MainFrame._user.getServerArray().get(0).getConnectionArray().size(); i++)
            {
                if (MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).getClient().getID()!=_client.getID())
                    MainFrame._user.getServerArray().get(0).getConnectionArray().get(i).writeSocket("REMOVE_CONTACT "+words[1]+" "+words[2]);
            }
            MainFrame._serverName.updateList();
            writeSocket("OK_BYE");
        }

        if (words[0].equals("OK_DELETE"))
            try {
                closeSocket();
        } catch (IOException ex) { Logger.getLogger(ConnectToServer.class.getName()).log(Level.SEVERE, null, ex); }
    }

    /**
     * This method writes to the socket.
     * @param str String to the socket.
     */
    public void writeSocket (String str)
    {
        _sendInfo.println(str);
        _sendInfo.flush();
    }

    /**
     * This method has to close the socket.
     * @throws IOException Faild to close socket.
     */
    public void closeSocket() throws IOException
    {
        try {
            _socket.close();
        } catch(InterruptedIOException e) {System.out.println("Erroe Close Socket!!!"); }
    }
}
